package org.opens.javaskill.design;

/**
 * 功能:
 * <p>策略模式的demo</p>
 */
public class StrategyPattern {

    public static void main(String[] args) throws Exception {
        OperationContext context = new OperationContext();
        context.setOperation(new AddOperation());
        System.out.println(context.execute(12, 23));

        context.setOperation(new SubOperation());
        System.out.println(context.execute(12, 23));

        context.setOperation(new MulOperation());
        System.out.println(context.execute(12, 23));

        Operation addOperation = OperationFactory.getInstance("+");
        Operation subOperation = OperationFactory.getInstance("-");
        Operation mulOperation = OperationFactory.getInstance("*");

        System.out.println(addOperation.execute(12, 23));
        System.out.println(subOperation.execute(12, 23));
        System.out.println(mulOperation.execute(12, 23));

        try {
            Operation divOperation = OperationFactory.getInstance("/");
            divOperation.execute(12, 23);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

/**
 * 说明:
 * <pre>
 *     1. 这个类是抽象策略类;
 * </pre>
 */
interface Operation {

    public int execute(int x, int y);

}

/**
 * 说明:
 * <pre>
 *     1. 这个类是加法策略的实现;
 * </pre>
 */
class AddOperation implements Operation {

    @Override
    public int execute(int x, int y) {
        return x + y;
    }

}

/**
 * 说明:
 * <pre>
 *     1. 这个类是减法策略的实现;
 * </pre>
 */
class SubOperation implements Operation {

    @Override
    public int execute(int x, int y) {
        return x - y;
    }

}

/**
 * 说明:
 * <pre>
 *     1. 这个类是乘法策略的实现;
 * </pre>
 */
class MulOperation implements Operation {

    @Override
    public int execute(int x, int y) {
        return x * y;
    }

}

/**
 * 说明:
 * <pre>
 *     1. 这个类封装了策略, 但是感觉不如使用一个工厂替代这个好.
 * </pre>
 */
class OperationContext {

    public Operation operation;

    public void setOperation(Operation operation) {
        this.operation = operation;
    }

    public int execute(int x, int y) {
        return this.operation.execute(x, y);
    }

}

class OperationFactory {

    private OperationFactory() {

    }

    public static Operation getInstance(String operator) throws Exception {
        Operation operation = null;
        switch (operator) {
            case "+":
                operation = new AddOperation();
                break;
            case "-":
                operation = new SubOperation();
                break;
            case "*":
                operation = new MulOperation();
                break;
            default:
                throw new Exception("不支持的操作");
        }
        return operation;
    }

}